
let { formatXmlObj, getSign } = require( '../method' );
let { intentM } = require( '../db' );
let { INTENT_STATE } = require( '../bussiness/config' );
let { NOT_PAY, SUCCESS_PAY, FAIL_PAY } = INTENT_STATE;
let informClient = require('./show');


// 查看订单是否处理过
const checkTheIntent = intent => {
  return new Promise( ( resolve, reject ) => {
    let { out_trade_no, state } = intent;
    if ( !out_trade_no ) reject( '我的数据库找不到这条订单' );

    // 未处理的订单
    if ( state === NOT_PAY ) {
      resolve( { isProcess: false, intentFromMyDb: intent } );
    } else {
      resolve( { isProcess: true, intentFromMyDb: intent } );
    }
  } );
};

const calMoneyFromDb = () => {
  return new Promise( ( resolve, reject ) => {
    intentM.get()
      .aggregate( [
        // 筛选所有支付成功的状态的记录
        {
          $match: { state: SUCCESS_PAY }
        },
        {
          $group: {
            // 计算所有的documents
            _id: null,
            totalValue: { $sum: "$total_fee" },
          }
        }
      ] )
      .toArray()
      .then( arr => {
        let document = arr[0] || {};
        let { totalValue } = document;
        resolve( totalValue );
      });
  } );

};

// 处理过的订单直接根据订单的信息向微信返回 确认
// 未处理过的订单处理后再跟微信确认
const processIntent = ( xmlObj, { isProcess, intentFromMyDb } ) => {
  return new Promise( ( resolve, reject ) => {
    if ( !isProcess ) {
      let result = checkIntentResultFromWeChat( xmlObj, intentFromMyDb );

      // 通过订单审核结果, 修改订单状态
      updateIntentState( xmlObj, result.isPass )
      // 计算当前赏金,
        .then( calMoneyFromDb )
        .then( sum => {
          informClient( 'money', { money: sum } )
        } )
      .catch( err => console.error(err));
      // 将赏金发回到客户端


      // result 格式({ isPass, errmsg })
      resolve( { isProcess: false, result } );

    } else {
      // 处理过， 根据处理结果向微信返回确认
      // 这里有疑点： 之前处理过是错误的，还要返回成功吗

      resolve( { isProcess: true } );
    }


  } );
};

// 对微信返回的订单处理状态进行验证
const checkIntentResultFromWeChat = ( xmlObj, intentFromDb ) => {
  let newObj = {};
  let { sign, fee_type, total_fee: total_fee_from_weChat } = xmlObj;
  let { total_fee: total_fee_from_db } = intentFromDb;
  for ( let key in xmlObj ) {
    if ( xmlObj.hasOwnProperty( key ) ) {
      if ( key !== 'sign' ) {
        newObj[ key ] = xmlObj[ key ];
      }
    }
  }

  let signGen = getSign( newObj );
  //  验证签名
  if ( signGen !== sign ) {

    return { isPass: false, errmsg: '签名校验不通过' };
  }

  // 验证金额
  if ( fee_type !== 'CNY' || parseInt( total_fee_from_weChat ) !== total_fee_from_db ) {
    return { isPass: false, errmsg: '微信返回的订单金额与系统后台的订单金额不同' };
  }

  return { isPass: true };
};

// 更新本地数据库的订单状态
const updateIntentState = ( xmlObj, isPass ) => {
  let intentCol = intentM.get();
  let { out_trade_no } = xmlObj;
  let state = FAIL_PAY;
  if ( isPass ) {
    state = SUCCESS_PAY;
  }

  return intentCol.updateOne( { out_trade_no }, { $set: { state } } );
};

// 向微信发送处理确认
const sendConfirmToWeChat = ( res, { isProcess, result = {} } ) => {

  let { isPass, errmsg } = result;
  let return_code = '';
  let return_msg = '';

  // 只有未被处理过的订支付结果以及未通过订单审核的支付结果会返回错误
  if ( !isProcess && !isPass ) {
    return_code = 'FAIL';
    return_msg = errmsg;
  } else {
    // 处理过的信息直接返回成功: 官方文档就是这样写的
    return_code = 'SUCCESS';
    return_msg = 'OK';
  }

  let xml = '<xml>' +
    '<return_code><![CDATA[' + return_code + ']]></return_code>' +
    '<return_msg><![CDATA[' + return_msg + ']]></return_msg>' +
    '</xml>';

  res.set( 'Content-Type', 'text/xml' );
  res.send( xml );

};


const inform = ( req, res ) => {
  // 收到来自微信后台的用于已经支付的确认
  // 提取出 xml 对象数据
  let { xml } = req.body;
  if ( !xml ) throw Error( '微信通知中没有放回xml' );

  let xmlObj = formatXmlObj( xml );

  let { out_trade_no, return_code } = xmlObj;

  if ( return_code === 'FAIL' ) {
    return;
  }


  //   appid: 'wx1fd2315008bbb7d1',
  //   bank_type: 'CFT',
  //   cash_fee: '1',
  //   fee_type: 'CNY',
  //   is_subscribe: 'Y',
  //   mch_id: '1494663462',
  //   nonce_str: '96853077',
  //   openid: 'okwwPvwxY6J2TJUIF9-2C0OHC87w',
  //   out_trade_no: '1517320768',
  //   result_code: 'SUCCESS',
  //   return_code: 'SUCCESS',
  //   sign: '6D6881BC35A2CAC3B68AD57C79255FB8',
  //   time_end: '20180130215815',
  //   total_fee: '1',
  //   trade_type: 'JSAPI',
  //   transaction_id: '4200000084201801303810247148' } '看看body是什么'


  // 根据在自家数据库中找到该订单号的订单, 并拿到订单状态
  let intentCol = intentM.get();

  intentCol.findOne( { out_trade_no } )
    .then( checkTheIntent )
    .then( processIntent.bind( this, xmlObj ) )
    .then( result => sendConfirmToWeChat( res, result ) )
    .catch( err => console.error( '处理微信返回的支付结果通知发生错误： ' + err ) );


};

module.exports = inform;